<?php

if (!defined('BASEPATH'))
    exit('No direct script access allowed');

/**
 * Parent Model for performing CRUD operations.
 * @package core
 * @category Metallica
 * 
 * @author Mark Angelo Angulo
 * @copyright (c) 2013
 */
class Metallica extends CI_Model {

    /**
     * @var string
     * Name of the database table to be manipulated. 
     */
    var $table = '';

    /**
     * Constructor Method.
     */
    function __construct()
    {
        parent::__construct();
        $this->load->database();
    }

    /**
     * Inserts a value to the database
     * @access public
     * @param array $data Associative Array containing information on the data being inserted to the database.
     * @return int Returns the id of the newly inserted row on the database.
     */
    function enter_sandman($data)
    {
        $this->db->insert($this->table, $data);
        return $this->db->insert_id();
    }

    /**
     * Retrieves one record from a database table using its id.
     * @access public
     * @param int $id The id of the content being retrieved from the database.
     * @param string $alias Comma Separated database attributes same to datatables header to be retrieved.
     * @return array|null Returns the row from the database as an array if id is found, otherwise null.
     */
    function one($id, $alias = '*')
    {
        if ($id == NULL)
        {
            return NULL;
        } else
        {
            $this->db->select($alias);
            $this->db->where('id', $id);
            $query = $this->db->get($this->table);

            $result = $query->result_array();
            return (count($result) > 0 ? $result[0] : NULL);
        }
    }

    /**
     * Retrieves one record from a database table using specific filters.
     * @access public
     * @param array $args Associative Array containing filters to the database query.
     * @param string $alias Comma Separated database attributes same to datatables header to be retrieved
     * @return array|null Returns the row from the database as an array if found, otherwise null.
     */
    function hero_of_the_day($args = array(), $alias = '*')
    {
        if (empty($args))
        {
            return NULL;
        } else
        {
            $this->db->select($alias);
            $this->db->where($args);
            $query = $this->db->get($this->table);

            $result = $query->result_array();
            return (count($result) > 0 ? $result[0] : NULL);
        }
    }

    /**
     * Retrieves record's specific attribute from a database table with certain filters.
     * @access public
     * @param array $args An array containing filters to the database query.
     * @param string $column The column/attribute being retrieved.
     * @return array|null Returns the value of the column/attribute if found, otherwise null.
     */
    function nothing_else_matters($args = array(), $column = NULL)
    {
        if (empty($args) OR $column == NULL)
        {
            return NULL;
        } else
        {
            $this->db->where($args);
            $query = $this->db->get($this->table);

            $result = $query->row_array();
            return (empty($result) ? NULL : $result[$column]);
        }
    }

    /**
     * Retrive a certain record. Create it if it doesn't exist.
     * @access public
     * @param array $args An array containing filters to the database query.
     * @param array $record An array containing the information about the record.
     * @return array Returns the record.
     */
    public function no_leaf_clover($args = array(), $record = array())
    {
        $this->db->where($args);
        $data = $this->db->get($this->table)->row_array();

        if (empty($data))
        {
            // if it doesn't exist, we create it.
            $id = $this->enter_sandman($record);
            return $id;
        } else
        {
            // otherwise return its ID.
            return $data['id'];
        }
    }

    /**
     * Retrieves an array of specific column from a database table.
     * @access public
     * @param array $args An array containing filters to the database query.
     * @param string $column The database column values to be retrieved.
     * @param int $offset Starting point of the records to be retrieved.
     * @param int $limit Number of records to be retrieved. Default is NULL or all records.
     * @param string $sort The name of the column where the records will be sorted example 'id'.
     * @param string $order Order of the records being retrieved values should either be 'asc' or 'desc'.
     * @return array Returns an array of filtered records.
     */
    function harvester_of_sorrow($args = array(), $column = NULL, $limit = NULL, $offset = 0, $order = 'asc')
    {
        if (empty($column) OR $column == NULL)
        {
            return NULL;
        } else
        {
            $this->db->order_by($column, $order);
            if (count($args) > 0)
            {
                $this->db->where($args);
            }

            $query = $this->db->get($this->table, $limit, $offset);

            $column_values = array();
            foreach ($query->result_array() as $query)
            {
                array_push($column_values, $query[$column]);
            }
            return $column_values;
        }
    }
    
    /**
     * Retrieves an array of specific column from a database table within a set of records.
     * @access public
     * @param array $arr A set of values to use as filter.
     * @param string $column The database column values to be retrieved.
     * @param string $column_select The database column to be compared from.
     * @param int $offset Starting point of the records to be retrieved.
     * @param int $limit Number of records to be retrieved. Default is NULL or all records.
     * @param string $sort The name of the column where the records will be sorted example 'id'.
     * @param string $order Order of the records being retrieved values should either be 'asc' or 'desc'.
     * @return array Returns an array of filtered records.
     */
    function harvester_of_sorrow_set($args = array(), $arr = array(), $column = NULL, $column_select ='id', $limit = NULL, $offset = 0, $order = 'asc')
    {
        if (empty($column) OR $column == NULL OR empty($arr) OR $arr == NULL)
        {
            return NULL;
        } else
        {
            $this->db->order_by($column, $order);
            
            if( count($arr) > 0)
            {
                $this->db->where_in($column_select, $arr);
            }
            
            if( count($args) > 0)
            {
                $this->db->where($args);
            }

            $query = $this->db->get($this->table, $limit, $offset);

            $column_values = array();
            foreach ($query->result_array() as $query)
            {
                array_push($column_values, $query[$column]);
            }
            return $column_values;
        }
    }

    /**
     * Retrieves limited number of records from a database table.
     * @access public
     * @param array $args An array containing filters to the database query.
     * @param string $alias Comma Separated database attributes same to datatables header to be retrieved.
     * @param int $offset Starting point of the records to be retrieved.
     * @param int $limit Number of records to be retrieved. Default is NULL or all records.
     * @param string $sort The name of the column where the records will be sorted example 'id'.
     * @param string $order Order of the records being retrieved values should either be 'asc' or 'desc'.
     * @return array Returns an array of limited records.
     */
    function and_justice_for_all($args = array(), $alias = '*', $limit = NULL, $offset = 0, $sort = 'id', $order = 'asc', $tables = NULL)
    {
        $this->db->order_by($sort, $order);
        $this->db->select($alias, FALSE);
        // filter query if arguments exists
        if (count($args) > 0)
        {
            $this->db->where($args);
        }
        
        if($tables != NULL)
        {
            foreach ($tables as $key => $table)
            {
                $this->db->join($key, $table);
            }
        }
        
        $query = $this->db->get($this->table, $limit, $offset);
        return $query->result_array();
    }
    
    /**
     * Retrieves limited number of records from a database table within a set of records.
     * @access public
     * @param array $arr A set of values to use as filter.
     * @param string $alias Comma Separated database attributes same to datatables header to be retrieved.
     * @param int $offset Starting point of the records to be retrieved.
     * @param int $limit Number of records to be retrieved. Default is NULL or all records.
     * @param string $sort The name of the column where the records will be sorted example 'id'.
     * @param string $order Order of the records being retrieved values should either be 'asc' or 'desc'.
     * @return array Returns an array of limited records.
     */
    function and_justice_for_all_set($args = array(), $arr = array(), $column_select = 'id', $alias = '*', $limit = NULL, $offset = 0, $sort = 'id', $order = 'asc', $tables = NULL)
    {
        $this->db->order_by($sort, $order);
        $this->db->select($alias, FALSE);

        if( count($arr) > 0)
        {
            $this->db->where_in($column_select, $arr);
        }

        if( count($args) > 0)
        {
            $this->db->where($args);
        }

        if($tables != NULL)
        {
            foreach ($tables as $key => $table)
            {
                $this->db->join($key, $table);
            }
        }

        $query = $this->db->get($this->table, $limit, $offset);
        return $query->result_array();
    }
    
    /**
     * Retrieves datatable formatted records.
     * @param string $alias Comma Separated database attributes same to datatables header.
     * @param array $args An array containing filters to the database query.
     * @param array $custom_column An array of columns to be customized.
     * @param boolean $checkbox TRUE if checkbox for each data should be generated.
     * @param boolean $options TRUE if edit and delete buttons should be generated.
     * @return json Returns json formatted datatable data.
     */
    function datallica_and_justice_for_all($args = array(), $alias = '*', $custom_column = array(), $options = '', $checkbox = TRUE, $tables = NULL)
    {
        $this->datatables->select($alias, FALSE);

        // join tables
        if($tables != NULL)
        {
            foreach ($tables as $key => $table)
            {
                $this->datatables->join($key, $table);
            }
        }

        // filter query if arguments exists
        if (count($args) > 0)
        {
            $this->datatables->where($args);
        }

        // add markup to columns
        if(count($custom_column) > 0)
        {
            foreach ($custom_column as $key => $column)
            {
                $this->datatables->edit_column($key, $column['markup'], $column['keys']);
            }
        }

        // create checkboxes for each data
        if($checkbox)
        {
            $this->datatables->edit_column('id','<input type="checkbox" name="items[]" class="item" value="$1">', 'id');
        } else
        {
            $this->datatables->unset_column('id');
        }

        // create buttons for data manipulation
        if($options)
        {
            $this->datatables->add_column('options', generate_options($options), 'id');
        }

        $this->datatables->from($this->table);
        return $this->datatables->generate();
    }
    
    /**
     * Retrieves datatable formatted records.
     * @param string $alias Comma Separated database attributes same to datatables header.
     * @param array $args An array containing filters to the database query.
     * @param array $custom_column An array of columns to be customized.
     * @param boolean $checkbox TRUE if checkbox for each data should be generated.
     * @param boolean $options TRUE if edit and delete buttons should be generated.
     * @return json Returns json formatted datatable data.
     */
    function datallica_and_justice_for_all_set($args = array(), $arr = array(), $column_select = 'id', $alias = '*', $custom_column = array(), $options = '', $checkbox = TRUE, $tables = NULL)
    {
        $this->datatables->select($alias, FALSE);
        
        if( count($arr) > 0)
        {
            $this->db->where_in($column_select, $arr);
        }
        
        // join tables
        if($tables != NULL)
        {
            foreach ($tables as $key => $table)
            {
                $this->datatables->join($key, $table);
            }
        }

        // filter query if arguments exists
        if ( count($args) > 0 )
        {
            $this->datatables->where($args);
        }

        // add markup to columns
        if(count($custom_column) > 0)
        {
            foreach ($custom_column as $key => $column)
            {
                $this->datatables->edit_column($key, $column['markup'], $column['keys']);
            }
        }

        // create checkboxes for each data
        if($checkbox)
        {
            $this->datatables->edit_column('id','<input type="checkbox" name="items[]" class="item" value="$1">', 'id');
        } else
        {
            $this->datatables->unset_column('id');
        }

        // create buttons for data manipulation
        if($options)
        {
            $this->datatables->add_column('options', generate_options($options), 'id');
        }

        $this->datatables->from($this->table);
        return $this->datatables->generate();
    }

    /**
     * Retrieves filtered number of records from a database table.
     * @access public
     * @param array $args An array containing filters to the database query.
     * @param string $search_term String used to filter database query.
     * @param int $offset Starting point of the records to be retrieved.
     * @param int $limit Number of records to be retrieved. Default is NULL or all records.
     * @param string $sort The name of the column where the records will be sorted example 'id'.
     * @param string $order Order of the records being retrieved values should either be 'asc' or 'desc'.
     * @return array Returns an array of filtered records.
     */
    function the_more_i_see($args = array(), $search_term = '', $alias = '*',  $limit = NULL, $offset = 0, $sort = 'id', $order = 'asc', $tables = NULL)
    {
        $this->db->order_by($sort, $order);
        $this->db->select($alias, FALSE);
        
        if($tables != NULL)
        {
            foreach ($tables as $key => $table)
            {
                $this->db->join($key, $table);
            }
        }
        
        if (count($args) > 0)
        {
            if(count($args) == 1)
            {
                $this->db->like($args[0], $search_term);
            } else
            {
                $this->db->like($args[0], $search_term);
                for($i = 1; $i < count($args); $i++)
                {
                    $this->db->or_like($args[$i], $search_term);
                }
            }
        }
        
        $query = $this->db->get($this->table, $limit, $offset);
        return $query->result_array();
    }
    
    /**
     * Retrieves filtered number of records from a database table.
     * @access public
     * @param array $args An array containing filters to the database query.
     * @param array $arr A set of values to use as filter.
     * @param string $column_select The database column to be compared from.
     * @param string $search_term String used to filter database query.
     * @param int $offset Starting point of the records to be retrieved.
     * @param int $limit Number of records to be retrieved. Default is NULL or all records.
     * @param string $sort The name of the column where the records will be sorted example 'id'.
     * @param string $order Order of the records being retrieved values should either be 'asc' or 'desc'.
     * @return array Returns an array of filtered records.
     */
    function the_more_i_see_set($args = array(), $arr = array(), $column_select = 'id', $search_term = '', $alias = '*',  $limit = NULL, $offset = 0, $sort = 'id', $order = 'asc', $tables = NULL)
    {
        if (count($arr) > 0)
        {
            $this->db->order_by($sort, $order);
            $this->db->select($alias, FALSE);
            
            if($tables != NULL)
            {
                foreach ($tables as $key => $table)
                {
                    $this->db->join($key, $table);
                }
            }
            
            if( count($arr) > 0)
            {
                $this->db->where_in($column_select, $arr);
            }

            if (count($args) > 0)
            {
                if(count($args) == 1)
                {
                    $this->db->where("(" . $this->table .".". $args[0] ." LIKE '%". $search_term . "%')");
                } else
                {
                    $like = "(" . $this->table .".". $args[0] ." LIKE '%". $search_term . "%' ";
                    for($i = 1; $i < count($args); $i++)
                    {
                        $like .= "OR " .$this->table .".". $args[$i] ." LIKE '%". $search_term . "%' ";
                    }
                    $like .= ")";
                    $this->db->where($like);
                }
            }
            
            $query = $this->db->get($this->table, $limit, $offset);
            return $query->result_array();
        } else
        {
            return NULL;
        }
    }
    
    /**
     * Retrieves filtered number of records from a database table.
     * @access public
     * @param array $args An array containing values to filter the query.
     * @param string $column Database column from which values are compared.
     * @param int $offset Starting point of the records to be retrieved.
     * @param int $limit Number of records to be retrieved. Default is NULL or all records.
     * @param string $sort The name of the column where the records will be sorted example 'id'.
     * @param string $order Order of the records being retrieved values should either be 'asc' or 'desc'.
     * @return array Returns an array of filtered records.
     */
    function all_within_my_hands($args = array(), $column = 'id', $limit = NULL, $offset = 0, $sort = 'id', $order = 'asc')
    {
        $this->db->order_by($sort, $order);
        if (count($args) > 0)
        {
            $this->db->where_in($column, $args);
        }
        $query = $this->db->get($this->table, $limit, $offset);
        return $query->result_array();
    }
    
    /**
     * Counts filtered number of records from a database table.
     * @access public
     * return int Returns number of records within a database table.
     */
    function all_nightmare_long($args = array(), $tables = NULL)
    {
        if (count($args) > 0)
        {
            $this->db->where($args);
        }
        
        if($tables != NULL)
        {
            foreach ($tables as $key => $table)
            {
                $this->db->join($key, $table);
            }
        }
        
        $query = $this->db->get($this->table);
        return $query->num_rows();
    }
    
    /**
     * Counts filtered number of records from a database table.
     * @access public
     * return int Returns number of records within a database table.
     */
    function all_nightmare_long_set($args = array(), $arr = array(), $column_select = 'id', $tables = NULL)
    {
        if( count($arr) > 0)
        {
            $this->db->where_in($column_select, $arr);
        }
        
        if (count($args) > 0)
        {
            $this->db->where($args);
        }
        
        if(count($arr) > 0)
        {
            $this->db->where_in($column_select, $arr);
        }
        
        if($tables != NULL)
        {
            foreach ($tables as $key => $table)
            {
                $this->db->join($key, $table);
            }
        }
        
        $query = $this->db->get($this->table);
        return $query->num_rows();
    }
    
    /**
     * Counts filtered/searched number of records from a database table.
     * @access public
     * @param array $args An array containing filters to the database query.
     * @param string $search_term String used to filter database query.
     * @return int Returns number of search records.
     */
    function the_end_of_the_line($args = array(), $search_term = '', $tables = NULL)
    {
        if($tables != NULL)
        {
            foreach ($tables as $key => $table)
            {
                $this->db->join($key, $table);
            }
        }
        
        if (count($args) > 0)
        {
            if(count($args) == 1)
            {
                $this->db->like($args[0], $search_term);
            } else
            {
                $this->db->like($args[0], $search_term);
                for($i = 1; $i < count($args); $i++)
                {
                    $this->db->or_like($args[$i], $search_term);
                }
            }
        }
        
        $query = $this->db->get($this->table);
        return $query->num_rows();
    }
    
    /**
     * Counts filtered/searched number of records from a database table.
     * @access public
     * @param array $args An array containing filters to the database query.
     * @param string $search_term String used to filter database query.
     * @return int Returns number of search records.
     */
    function the_end_of_the_line_set($args = array(), $arr = array(), $column_select = 'id', $search_term = '', $tables = NULL)
    {
        if($tables != NULL)
        {
            foreach ($tables as $key => $table)
            {
                $this->db->join($key, $table);
            }
        }
        
        if( count($arr) > 0 )
        {
            $this->db->where_in($column_select, $arr);
        }
        
        if (count($args) > 0)
        {
            if(count($args) == 1)
            {
                $this->db->where("(" . $this->table .".". $args[0] ." LIKE '%". $search_term . "%')");
            } else
            {
                $like = "(" . $this->table .".". $args[0] ." LIKE '%". $search_term . "%' ";
                for($i = 1; $i < count($args); $i++)
                {
                    $like .= "OR " .$this->table .".". $args[$i] ." LIKE '%". $search_term . "%' ";
                }
                $like .= ")";
                $this->db->where($like);
            }
        }
        
        $query = $this->db->get($this->table);
        return $query->num_rows();
    }
    
    /**
     * Updates a record from a database table.
     * @access public
     * @param array $data An array containing new information about the record being updated.
     * @param array $args Arguments to which row/s will be updated.
     */
    function the_memory_remains($args = array(), $data = NULL)
    {
        if (count($args) > 0)
        {
            $this->db->where($args);
            $this->db->update($this->table, $data);
            return $this->db->affected_rows();
        } else
        {
            return NULL;
        }
    }
    
    /**
     * Updates multiple records from a database table.
     * @access public
     * @param array $data An array containing new information about the record being updated.
     * @param array $arr Arguments to which row/s will be updated.
     */
    function master_of_puppets($arr = array(), $column = 'id', $data = NULL)
    {
        if (count($arr) > 0)
        {
            $this->db->where_in($column, $arr);
            $this->db->update($this->table, $data);
            return $this->db->affected_rows();
        } else
        {
            return NULL;
        }
    }
    
    /**
     * Change status to archived. Usually used for records that can't be deleted due to constraints
     * @param array $values Array of values to be deleted
     * @param int $attribute Databse attribute/column from where the values are checked
     * @return string Returns database errors if any
     */
    function until_it_sleeps($values = array(), $attribute = 'id')
    {
        if (empty($values))
        {
            return NULL;
        } else
        {
            $archived = array();
            
            foreach ($values as $value)
            {
                $this->db->where($attribute, $value);
                $this->db->delete($this->table);
                $error_msg = $this->db->_error_message();
                
                // if we cannot delete it, change it's status to archived
                if($error_msg)
                {
                    $this->db->where($attribute, $value);
                    $this->db->update($this->table, array('status' => 'archived'));
                    array_push($archived, $value);
                    continue;
                }
            }
            return $archived;
        }
    }

    /*
     * Removes a record from a database table.
     * @access public
     * @param int id Integer representing the ID of the record that will be deleted.
     * @return string Returns database errors if any
     */

    function seek_and_destroy($args = array())
    {
        if (empty($args))
        {
            return NULL;
        } else
        {
            $this->db->where($args);
            $this->db->delete($this->table);

            $error_msg = $this->db->_error_message();
                
            // if we cannot delete it, change it's status to archived
            if($error_msg)
            {
                $this->db->where($args);
                $this->db->update($this->table, array('status' => 'archived'));
                return 'archived';
            } else
            {
                return 'deleted';
            }
            
        }
    }

    /**
     * Deletes Multiple records according to the specified database column/attribute
     * @access public
     * @param array $values Array of values to be deleted
     * @param int $attribute Databse attribute/column from where the values are checked
     * @return string Returns database errors if any
     */
    function disposable_heroes($values = array(), $attribute = 'id')
    {
        if (empty($values))
        {
            return NULL;
        } else
        {
            $this->db->where_in($attribute, $values);
            $this->db->delete($this->table);
            return $this->db->_error_message();
        }
    }

    /**
     * Clears a database table.
     * @return string Returns database errors if any
     */
    function fade_to_black()
    {
        $this->db->delete($this->table);
        return $this->db->_error_message();
    }
    
    // whiskey in the jar
    public function whiskey_in_the_jar($field_name)
    {
        if ($this->db->field_exists($field_name, $this->table))
        {
            return $field_name;
        } else
        {
            return $this->table . '.id';
        }
    }
}

/* End of file Metallica.php */
/* Location: ./system/application/core/Metallica.php */